package cc.rengu.igas.share.core.service.channel.upqc;

import cc.rengu.igas.channel.upqc.facade.base.Header;
import cc.rengu.igas.channel.upqc.facade.bean.CouponInfoBean;
import cc.rengu.igas.channel.upqc.facade.bean.PayerInfo;
import cc.rengu.igas.channel.upqc.facade.bean.RiskInfoBean;
import cc.rengu.igas.channel.upqc.facade.request.B2COrderPayRequest;
import cc.rengu.igas.channel.upqc.facade.response.B2COrderPayResponse;
import cc.rengu.igas.channel.upqc.facade.result.Result;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * UPQC付款
 * Created by lzl on 2021/4/23 11:08
 */
public class B2cOrderPayService extends ChannelBaseService {
    @Override
    public Object callPreProc(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Header upqcHeader = new Header();
        upqcHeader.setInstId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID));
        upqcHeader.setChanlId(channelCallCfg.getMsgSrcId());
        upqcHeader.setSrcSysId(AppParamConstant.SYS_ID);
        upqcHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        upqcHeader.setVersion(ShareParamConstant.DUBBO_VSERSION);
        upqcHeader.setTxnNum(channelCallCfg.getCallChannelTxn());
        upqcHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        upqcHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        upqcHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        B2COrderPayRequest b2COrderPayRequest = new B2COrderPayRequest();
        ConvertUtil.convertOutput(b2COrderPayRequest);
        b2COrderPayRequest.setHeader(upqcHeader);
        SignAcctInfo signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);

        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        /*银联机构号*/
        b2COrderPayRequest.setIssInsCode(xmlTreeUtil.getXmlTreeStringValue("unonPayCode"));
        /*订单金额	orderAmt*/
        b2COrderPayRequest.setOrderAmt(userOrderInfo.getRealPayAmt());
        /*交易币种*/
        b2COrderPayRequest.setOrderCcy(userOrderInfo.getOrderCcy());
        /* 交易顺序号txnNo*/
        b2COrderPayRequest.setTxnNo(userOrderInfo.getSysSeqNum());
        /*付款方信息payerInfo*/
        PayerInfo payerInfo = new PayerInfo();
        /*新卡签约支付只能是本行卡*/
        payerInfo.setAccNo(xmlTreeUtil.getXmlTreeStringValue("acctNo"));
        // card_hold_name
        payerInfo.setName(xmlTreeUtil.getXmlTreeStringValue("cardHoldName"));
        /*贷记卡判断 1-借记卡*/
        if ("1".equals(xmlTreeUtil.getXmlTreeStringValue("cardType"))) {
            payerInfo.setCardAttr("01"); // 借记卡
        } else {
            payerInfo.setCardAttr("02"); // 贷记卡
        }
        /*预留手机号*/
        payerInfo.setMobile(Objects.requireNonNull(signAcctInfo).getReserveMobileNo());
        b2COrderPayRequest.setPayerInfo(payerInfo);
        /*风控信息riskInfo*/
        RiskInfoBean riskInfo = new RiskInfoBean();
        if (StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue("riskInfo/devId"))) {
            riskInfo.setDeviceID("DevId");
        } else {
            riskInfo.setDeviceID(xmlTreeUtil.getXmlTreeStringValue("riskInfo/devId"));
        }
        if (StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue("riskInfo/deviceMode"))) {
            riskInfo.setDeviceName("DeviceMode");
        } else {
            riskInfo.setDeviceName(xmlTreeUtil.getXmlTreeStringValue("riskInfo/deviceMode"));
        }
        if (StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue("riskInfo/termIp"))) {
            riskInfo.setSourceIP("127.0.0.1");
        } else {
            riskInfo.setSourceIP(xmlTreeUtil.getXmlTreeStringValue("riskInfo/termIp"));
        }
        riskInfo.setDeviceLocation(xmlTreeUtil.getXmlTreeStringValue("riskInfo/deviceLocation"));
        if (StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue("riskInfo/deviceMode"))) {
            riskInfo.setDeviceType("DeviceType");
        } else {
            riskInfo.setDeviceType(xmlTreeUtil.getXmlTreeStringValue("riskInfo/deviceMode"));
        }
        //应用提供方账户ID
        if (!StringUtil.isEmptyOrNull(signAcctInfo.getUserId())) {
            riskInfo.setAccountIdHash(MD5Util.MD5Encode(signAcctInfo.getUserId()));
        }
        //银行预留手机号
        if (!StringUtil.isEmptyOrNull(signAcctInfo.getReserveMobileNo())) {
            riskInfo.setMobile(signAcctInfo.getReserveMobileNo());
        }
        //账户注册日期  8 位日期字符 yyyymmdd
        if (!StringUtil.isEmptyOrNull(signAcctInfo.getCreateTime())) {
            riskInfo.setUsrRgstrDt(DateUtil.dateStringFormatConvert(signAcctInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss.SSS", "yyyyMMdd"));
        }
        b2COrderPayRequest.setRiskInfoBean(riskInfo);
        List<CouponInfoBean> couponInfoBeanList = null;
        // 如果存在营销
        if (!StringUtil.isEmptyOrNull(userOrderInfo.getDiscountInfo())) {
            List<CouponInfoBean> couponInfoList = JSON.parseArray(userOrderInfo.getDiscountInfo(), CouponInfoBean.class);
            if (!couponInfoList.isEmpty()) {
                CouponInfoBean couponInfoBean = couponInfoList.get(0);
                couponInfoBeanList = new ArrayList<>();
                // 只向银联传送第一条优惠
                couponInfoBeanList.add(couponInfoBean);
            }
        }

        /*使用优惠卷*/
        if (couponInfoBeanList != null) {
            /* 初始交易金额 */
            b2COrderPayRequest.setOrigTxnAmt(userOrderInfo.getOrderAmt());
            /*银联返回的优惠信息*/
            b2COrderPayRequest.setCouponInfoList(couponInfoBeanList);
        }

        rglog.debug("UPQC付款请求:<{}>", JSON.toJSONString(b2COrderPayRequest));
        return b2COrderPayRequest;
    }

    @Override
    public PayOrderInfo generatePayOrderInfo(ChannelCallCfg channelCallCfg, OrderInfo orderInfo, Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        B2COrderPayRequest b2COrderPayRequest = (B2COrderPayRequest) request;
        BeanUtil.beanCopy(orderInfo.getUserOrderInfo(), payOrderInfo);
        if (orderInfo.getMchntOrderInfoList().size() == 1) {
            payOrderInfo.setMchntNo(orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
        } else {
            payOrderInfo.setMchntNo(orderInfo.getUserOrderInfo().getGroupMchntNo());
        }
        payOrderInfo.setTxnNum(channelCallCfg.getTxnNum());
        payOrderInfo.setBizType(channelCallCfg.getBizType());
        payOrderInfo.setSysSeqNum(orderInfo.getUserOrderInfo().getSysSeqNum());
        payOrderInfo.setOrderCcy(orderInfo.getUserOrderInfo().getOrderCcy());
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(Objects.requireNonNull(b2COrderPayRequest).getHeader().getTraceNo());
        payOrderInfo.setChannelReconKey(b2COrderPayRequest.getHeader().getTraceNo());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setPayType(PayTypeEnum.CUPS_CLOUD.getPayType());
        payOrderInfo.setPayerAcctType(AcctTypeEnum.ALL.getAcctType());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        payOrderInfo.setUserId(orderInfo.getUserOrderInfo().getUserId());
        return payOrderInfo;
    }

    @Override
    public Object callProc(ChannelCallCfg channelCallCfg, Object request) throws Exception {
        B2COrderPayRequest b2COrderPayRequest = (B2COrderPayRequest) request;
        /* Step1：调用接口，获取结果 */
        Result<B2COrderPayResponse> callResult;
        DubboService dubboService = new DubboServiceImpl();
        if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
            /* Step1.1：异步调用 */
            int iReturnCode;
            int callTimes = 0 == channelCallCfg.getSyncQueryRepeatNum() ? 1 : channelCallCfg.getSyncQueryRepeatNum();
            int gatTime = channelCallCfg.getSyncQueryRepeatTime();
            int gatType = StringUtil.isEmptyOrNull(channelCallCfg.getSyncQueryGapType()) ? 0 : Integer.parseInt(channelCallCfg.getSyncQueryGapType());
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.1：异步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPQC_PAYER_SERVICE_INNER_PATH);
                iReturnCode = dubboService.asynCallDubboInnerMethod(clasz, ShareServiceConstant.UPQC_B2C_ORDER_PAY_METHOD, b2COrderPayRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.2：异步远程调用 */
                iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.UPQC_PAYER_SERVICE, ShareServiceConstant.UPQC_B2C_ORDER_PAY_METHOD, b2COrderPayRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
            if (0 == iReturnCode) {
                return new BizResponse<>(OltpRpcdEnum.TRANS_SUCCESS.getRespCode(), OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            } else {
                return new BizResponse<>(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            }
        } else {
            /* Step1.2：同步调用 */
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.1：同步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPQC_PAYER_SERVICE_INNER_PATH);
                callResult = (Result<B2COrderPayResponse>) dubboService.callDubboInnerMethod(clasz, ShareServiceConstant.UPQC_B2C_ORDER_PAY_METHOD, b2COrderPayRequest);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.2：同步远程调用 */
                callResult = (Result<B2COrderPayResponse>) dubboService.callDubboService(ShareServiceConstant.UPQC_PAYER_SERVICE, ShareServiceConstant.UPQC_B2C_ORDER_PAY_METHOD, b2COrderPayRequest);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
        }
        return callResult;
    }

    @Override
    public Object querySyncCallResult(PayOrderInfo payOrderInfo, Object request) {
        return null;
    }

    @Override
    public OrderInfo callResultOrderProc(OrderInfo orderInfo, String payOrderIndex, TransStatusEnum transStatusEnum, Object response) {
        OrderInfo updateOrderInfo = new OrderInfo();
        Result<B2COrderPayResponse> callResult = (Result<B2COrderPayResponse>) response;
        Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item -> item.getDstCallIndex().equals(payOrderIndex)).findFirst();
        if (payOrderInfoOpt.isPresent() && null != callResult && null != callResult.getResult()) {
            B2COrderPayResponse b2COrderPayResponse = callResult.getResult();
            PayOrderInfo payOrderInfo = payOrderInfoOpt.get();
            payOrderInfo.setTransStatus(transStatusEnum.getStatus());
            payOrderInfo.setRespCode(b2COrderPayResponse.getRespCode());
            payOrderInfo.setRespDesc(b2COrderPayResponse.getRespDesc());
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            switch (transStatusEnum) {
                case TRANS_SUCC:
                    payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    /* 用户订单信息处理 */
                    updateOrderInfo.setUserOrderInfo(orderInfo.getUserOrderInfo());
                    /* 商户订单信息处理 */
                    payOrderInfo.setSettleDate(DateUtil.getCurrentDate());

                    break;
                case TRANS_TIMEOUT:
                    payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                    break;
                case SYSTEM_REJECT:
                    payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    break;
                default:
                    break;
            }
            List<PayOrderInfo> payOrderInfoList = new ArrayList<>();
            payOrderInfoList.add(payOrderInfo);
            updateOrderInfo.setPayOrderInfoList(payOrderInfoList);
        }
        return updateOrderInfo;
    }
}
